//
//	File: OyRenderDevice.h
//

#ifndef OYRENDERDEVICE_H
#define OYRENDERDEVICE_H

#include <windows.h>
#include <stdio.h>

#include "OyEngine.h"

// S T R U C T S ///////////////////////////////////////////////////

/**
 * OySkinManager is an abstract class which provides an interface
 * from which material managers can inherit. Those heirs need to 
 * implement a store for texture data in a way appropriate to the
 * API.
 */
class OySkinManager 
{
public:
    OySkinManager(void) {};
    virtual ~OySkinManager(void) {};

    virtual void        Reset(void) = 0;
    virtual HRESULT     AddSkin(const OyColor *pcAmbient,
                                const OyColor *pcDiffuse,
                                const OyColor *pcEmissive,
                                const OyColor *pcSpecular,
                                float fSpecPower,
                                UINT *nSkinID) = 0;
	virtual void		SetAlphaToSkin(UINT nSkinID, bool bAlpha) = 0;
	virtual void		SetAlphaTestToSkin(UINT nSkinID, bool bAlphaTest) = 0;
	virtual void		SetPrimitiveTypeToSkin(UINT nSkinID, char PrimitiveType) = 0;
    virtual HRESULT     AddTexture(UINT nSkinID, const TCHAR *chName, UINT slot = 0) = 0;
    virtual HRESULT     AddTextureHeightmapAsBump(UINT nSkinID, const TCHAR *chName, UINT slot = 0) = 0;

    //virtual HRESULT     ExchangeTexture(UINT nSkinID, UINT nTexStage, const char *chName ) = 0;

    //virtual HRESULT     ExchangeMaterial(UINT nSkinID,
    //                                 const OyColor *pcAmb,
    //                                 const OyColor *pcDif,
    //                                 const OyColor *pcEmis,
    //                                 const OyColor *pcSpec,
    //                                 float fSpecPower) = 0;

    virtual bool        MaterialEqual(	const OyMaterial *pMat0, 
										const OyMaterial *pMat1) = 0;
    virtual bool        ColorEqual(	const OyColor *pCol0, 
                                    const OyColor *pCol1) = 0;

    //virtual void        LogCurrentStatus(char *chLog, 
    //                                     bool bDetailed)=0;

	virtual UINT			GetNumSkins(void) = 0;
	virtual OySkin			GetSkin(UINT nSkinID) = 0;
	virtual OyMaterial		GetMaterial(UINT nMatID) = 0;
	virtual const TCHAR*	GetTextureName(UINT nTexID) = 0;
	virtual const void*		GetOyTextureData(UINT TexID) = 0;
};

/**
 * Class to manage static and dynamic vertex bunches, optionally
 * using indices during rendering process.
 */
class OyVertexCacheManager
{
public:
    OyVertexCacheManager(void) {};
	virtual ~OyVertexCacheManager(void) {};

    virtual HRESULT		CreateStaticBuffer(
											OY_VERTEXTYPE VertexType,
											UINT  nSkinID,
											UINT  nVertexNum, 
											UINT  nIndexNum, 
											const void *pVerts,
											const WORD *pIndis,
											UINT *pnID ) = 0;
	virtual void		ClearAllStaticBuffer() = 0;
	virtual HRESULT		ClearStaticBuffer( UINT nSBufferID ) = 0;

	virtual HRESULT		RenderStaticBuffer( UINT nSBufferID ) = 0;
	virtual HRESULT		RenderStaticBuffer( UINT nSBufferID, UINT SkinID ) = 0;
      
    virtual HRESULT		RenderDynamicBuffer(OY_VERTEXTYPE VertexType,
											UINT nSkinID,
											UINT nVertexNum, 
											UINT nIndexNum, 
											const void *pVerts,
											const WORD *pIndis ) = 0;

    virtual HRESULT		RenderPoints(	OY_VERTEXTYPE	VertexType,
										UINT            nVertexNum,
										const void		*pVerts,
										const OyColor	*pColor ) = 0;

    virtual HRESULT		RenderLines(	OY_VERTEXTYPE   VertexType,
										UINT            nVertexNum,
										const void		*pVerts,
										const OyColor	*pColor,
										bool            bStrip ) = 0;

    virtual HRESULT		RenderLine(		const float *fStart,
										const float *fEnd, 
										const OyColor *pColor ) = 0;

	virtual HRESULT		RenderTriangles(	OY_VERTEXTYPE	VertexType,
											UINT            nVertexNum,
											UINT			nIndexNum,
											const void		*pVerts,
											const WORD		*pIndis,
											const UINT		MaterialID,
											const UINT		ModifierID,
											char*			CustomMaterialStr,
											const UINT		SkinID ) = 0;

    virtual HRESULT		ForcedCommitAll(void) = 0;
	virtual HRESULT		ForcedClearAll(void) = 0;

	virtual	void		OnDeviceLost(void) = 0;
	virtual void		OnDeviceReset(void) = 0;

    //virtual HRESULT		ForcedCommit(OY_VERTEXTYPE) = 0;

    //  virtual void    InvalidateStates(void)=0;

    //  virtual ZFXRENDERSTATE GetShadeMode(void)=0;
};

/**
 * OyRenderDevice is an abstract class which provides an interface
 * from which render dll's can inherit. This secures availability
 * of the necessary render functions.
 */
class OyRenderDevice
{
public:
	OyRenderDevice(void) { };
	virtual ~OyRenderDevice(void) { };

	// Manager:
	virtual OySkinManager* GetSkinManager(void) = 0;
	virtual OyVertexCacheManager* GetVertexCacheManager(void) = 0;

	// Initialize:
	// initialize engine
	virtual HRESULT		Init(HWND hWnd, const HWND *hWnd3D, int nNumhWnd, int nMinDepth, int nMinStencil) = 0;
	virtual void		OnDeviceReset(void) = 0;

    // release API specific stuff
	virtual void		Release(void) = 0;
	virtual bool		IsRunning(void) = 0;

	// Rendering:
	// switch swap chain to hwnd in array
	virtual HRESULT		UseWindow(UINT nHwnd) = 0;
	virtual HRESULT		BeginRendering( bool bClearPixel, 
										bool bClearDepth, 
										bool bClearStencil ) = 0;
	virtual void		EndRendering() = 0;
	virtual void		FlushRenderBatch() = 0;
	virtual HRESULT		Clear(bool bClearPixel, bool bClearDepth, bool bClearStencil) = 0;
	virtual void		SetClearColor(float fRed, float fGreen, float fBlue) = 0;
	virtual void		GetScreenResolution(POINT* pt) = 0;

	// LIGHT STUFF:
	// set ambient light
    virtual void		SetAmbientLight(float fRed, float fGreen, float fBlue) = 0;

	// CAMERA STUFF:
    // set mode for current camera, 0:=3D(perspective), 1:=3D(orthogonal) 2:=2D
    virtual HRESULT		SetMode(OY_CAMERAMODE Mode) = 0; 
	
	// Set/Get viewport for current camera
	virtual HRESULT		SetViewPort(OY_VIEWPORT* pViewPort) = 0;
	virtual HRESULT		GetViewPort(OY_VIEWPORT* pViewPort) = 0;

    // set current camera near and far clipping plane
    virtual void		SetClippingPlanes(float fNear, float fFar) = 0;

    // set perspective FOV and Aspect for current camera to Build Project Matrix
    virtual HRESULT		SetProjMatrixParams(float fFOV, float fAspect) = 0;

	// set current view matrix from cam's vRight, vUp, vDir, vPos (must be normalized vector)
    virtual HRESULT		SetViewMatrix3D(const OyVector4D& vcRight, const OyVector4D& vcUp, 
								const OyVector4D& vcDir, const OyVector4D& vcEyePos) = 0;

    // set current view matrix: EyePos, Lookat, world up (could be un-normalized vector)
    virtual HRESULT		SetViewMatrixLookAt(const OyVector4D& vcPos, const OyVector4D& vcPoint, 
								const OyVector4D& vcWorldUp) = 0;

    // get frustrum planes / View Matrix / Proj Matrix
    virtual HRESULT		GetFrustrum(OyPlane *pPlane) = 0;
	virtual void		GetViewMatrix(float *pMat) = 0;
	virtual void		GetProjMatrix(float *pMat) = 0;

    // screen to worldray, give 2 vectors for output
    virtual void		Transform2Dto3D(const POINT &pt, OyVector4D *vcOrig, OyVector4D *vcDir) = 0;

    // cast world position to screen coordinates
    virtual POINT		Transform3Dto2D(const OyVector4D &vcP) = 0;

	// FONT STUFF:
	// Prepare something for Rendering text in screen. (must called before DrawTextInPos())
	virtual void		BeginRenderText() = 0;
	// After something for Rendering text in screen. (must called after DrawTextInPos())
	virtual void		EndRenderText() = 0;

	virtual void		SetActiveFont(const char* FontName) = 0;

	// type like "Arial", nWeight (0=default,700=bold), italic?, 
    // underline?, strike out?, size, return ID
    virtual HRESULT		CreateFontInManager(const char* FontName, const char* FontFilePath, bool bBold, bool bItalic, DWORD dwSize) = 0;

    // draw text: font id, x, y, r, g, b, format string, variables
    virtual HRESULT		DrawTextInPos(int xPos, int yPos, DWORD flag, float RealFontSize, UCHAR r, UCHAR g, UCHAR b, TCHAR* format, ...) = 0;

	virtual void		PreCacheChar(const TCHAR* sText) = 0;
};

typedef class OyRenderDevice *LPOYRENDERDEVICE;

/*----------------------------------------------------------------*/
extern "C" 
{
	HRESULT CreateRenderDevice(HINSTANCE hDLL, OyRenderDevice **pInterface);
	typedef HRESULT (*CREATERENDERDEVICE)(HINSTANCE hDLL, OyRenderDevice **pInterface);
   
	HRESULT ReleaseRenderDevice(OyRenderDevice **pInterface);
	typedef HRESULT (*RELEASERENDERDEVICE)(OyRenderDevice **pInterface);
}
/*----------------------------------------------------------------*/

#endif